layui.define(['element', 'laytpl', 'jquery', 'miniAdmin'], (exports) => {
    const element = layui.element
    const $ = layui.$
    const layer = layui.layer
    const miniAdmin = layui.miniAdmin

    const config = {
        dev: true,
        baseUrl: 'http://localhost:4052',
        tokenKey: 'token',
        apiUrl: 'http://localhost:4050',
        successCode: '00000000',
        lastCodeKey: 'last_code'
    }

    const isDev = () => {
        return config.dev
    }

    const getStorage = (type) => {
        if (!type) {
            return window.localStorage
        }
        if (1 === type) {
            return window.localStorage
        }
        return window.sessionStorage
    }

    /**
     * 获取值
     * @param key
     * @param type
     * @returns {*}
     */
    const getValue = (key, type = 1) => {
        const storage = getStorage(type)
        return storage.getItem(key)
    }

    /**
     * 保存值
     * @param key
     * @param value
     * @param type
     */
    const setValue = (key, value, type) => {
        const storage = getStorage(type)
        storage.setItem(key, value)
    }

    /**
     * 获取 token
     * @returns {string}
     */
    const getToken = () => {
        const storage = getStorage()
        return storage.getItem(config.tokenKey)
    }

    /**
     * 设置 token
     * @param token
     */
    const setToken = (token) => {
        const storage = getStorage()
        storage.setItem(config.tokenKey, token)
    }

    const setLastCode = (code) => {
        const storage = getStorage()
        storage.setItem(config.lastCodeKey, code)
    }

    const getLastCode = () => {
        const storage = getStorage()
        return storage.getItem(config.lastCodeKey)
    }

    const storeUtil = {
        getValue,
        setValue,
        getToken,
        setToken,
        getLastCode
    }

    /**
     * ajax 请求成功后的处理
     * @param data 服务端返回的数据 rsp.body
     * @param successFunc 数据处理回调
     * @returns {*}
     */
    const successHandle = (data, successFunc) => {
        if (null == successFunc) {
            return data
        }
        const result = successFunc(data)
        return result ? result : data
    }

    /**
     * 通用请求方法
     */
    const request = ({
        url = null,
        method = 'GET',
        async = false,
        data = null,
        stringFly = true,
        successFunc = null,
        failFunc = null,
        statusCode = null
    } = {}) => {
        let result = null
        const _url = config.apiUrl + url

        let option = {}
        option.url = _url
        option.method = method
        option.async = async
        if ('get' === method.toLowerCase()) {
            option.data = data
        } else if ('post' === method.toLowerCase()) {
            if (stringFly) {
                option.data = JSON.stringify(data)
                option.contentType = 'application/json;charset=utf-8'
            } else {
                option.data = data
            }
        }

        const token = storeUtil.getToken()
        if (undefined !== token && null != token) {
            option.headers = {
                'Authorization': 'Bearer ' + token
            }
        }
        if (isDev()) {
            console.log('↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓')
            console.log('req: url:', _url)
            console.log('req: method:', method)
            if (option.data) {
                console.log('req: data:',
                    stringFly && 'post' === method.toLowerCase() ?
                        JSON.parse(option.data) :
                        option.data)
            }
        }

        option.success = (rsp) => {
            if (isDev()) {
                console.log('rsp:', rsp)
                console.log('↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑')
            }
            const code = rsp.code
            const body = rsp.body
            setLastCode(code)
            if (code === config.successCode) {
                if (null == statusCode) {
                    result = successHandle(body, successFunc)
                } else {
                    if (undefined === statusCode[rsp.code] || null == statusCode[rsp.code]) {
                        result = successHandle(body, successFunc)
                    } else {
                        statusCode[rsp.code](body)
                    }
                }
            } else {
                if (null != failFunc) {
                    failFunc(body)
                } else {
                    if (null != statusCode && null != statusCode[code]) {
                        statusCode[code](body)
                    } else {
                        miniAdmin.error(rsp.msg)
                    }
                }
            }
        }

        option.error = (e) => {
            if (404 === e.status) {
                miniAdmin.error('请求路径不存在')
            } else if (403 === e.status) {
                miniAdmin.error('无权限进行此操作')
            } else if (500 === e.status) {
                miniAdmin.error('服务器内部错误')
            }
        }

        $.ajax(option)

        return result
    }

    /**
     * <p>index 加载时调用</p>
     * <p>pluto 初始化</p>
     */
    const plutoInit = () => {
        console.log('pluto init start')

        // ajax 统一 headers
        // todo 优化 : 日志与配置
        const token = storeUtil.getToken()
        if (token) {
            console.log('pluto ajax setup')
            $.ajaxSetup({
                headers: {
                    'Authorization': 'Bearer ' + token
                }
            })
        }

        console.log('pluto init end')
    }

    /**
     * 构造请求地址
     * @param url 相对路径
     */
    const buildUrl = (url) => {
        return config.apiUrl + url
    }

    /**
     * 将后端分页数据转换为layui表格数据结构
     */
    const transTableData = (rsp) => {
        return {
            code: config.successCode === rsp.code ? 0 : 1,
            msg: rsp.msg,
            count: rsp.total,
            data: rsp.body.list
        }
    }

    /**
     * 将 form 数据转为 json 对象
     * @param $form 表单jquery对象
     */
    const getFormData = ($form) => {
        let data = {}
        const formArray = $form.serializeArray()
        if (formArray.length > 0) {
            formArray.forEach((item) => {
                data[item.name] = item.value
            })
        }
        return data
    }

    const isLastAjaxSuccess = ()=>{
        return config.successCode === getLastCode();
    }

    const pluto = {
        config,
        storeUtil,
        request,
        plutoInit,
        buildUrl,
        transTableData,
        getFormData,
        isLastAjaxSuccess

    }


    exports('pluto', pluto)
})
